package com.xwaf.platform.web.config.netty;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.xwaf.platform.common.api.entity.netty.WebSocketNettyUsers;

import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPromise;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.websocketx.WebSocketClientHandshaker;
import io.netty.util.CharsetUtil;

public class WebSocketNettyClientHandler extends SimpleChannelInboundHandler<Object> {

	private static final Logger LOGGER = LoggerFactory.getLogger(WebSocketNettyClientHandler.class);

	private final WebSocketClientHandshaker webSocketClientHandshaker;

	private ChannelPromise handshakeFuture;

	public WebSocketNettyClientHandler(WebSocketClientHandshaker webSocketClientHandshaker) {
		this.webSocketClientHandshaker = webSocketClientHandshaker;
	}

	@Override
	public void handlerAdded(ChannelHandlerContext ctx) {
		handshakeFuture = ctx.newPromise();
	}

	/**
	 * 异常
	 *
	 * @param channelHandlerContext
	 *            channelHandlerContext
	 * @param cause
	 *            异常
	 */
	@Override
	public void exceptionCaught(ChannelHandlerContext channelHandlerContext, Throwable cause) throws Exception {
		LOGGER.info("├ [exception]: {}", cause.getMessage());
		// 移出通道
		WebSocketNettyUsers.remove(channelHandlerContext.channel());
		channelHandlerContext.close();
	}

	/**
	 * 当客户端主动链接服务端的链接后，调用此方法
	 *
	 * @param channelHandlerContext
	 *            ChannelHandlerContext
	 */
	@Override
	public void channelActive(ChannelHandlerContext channelHandlerContext) throws Exception {
		LOGGER.info("├ [建立连接]");

		Channel channel = channelHandlerContext.channel();
		// 握手
		webSocketClientHandshaker.handshake(channel);
	}

	/**
	 * 与服务端断开连接时
	 *
	 * @param channelHandlerContext
	 *            channelHandlerContext
	 */
	@Override
	public void channelInactive(ChannelHandlerContext channelHandlerContext) {
		Channel channel = channelHandlerContext.channel();
		// // 移出通道
		LOGGER.info("├ [断开连接]：client [{}]", channel.remoteAddress());

	}

	/**
	 * 读完之后调用的方法
	 *
	 * @param channelHandlerContext
	 *            ChannelHandlerContext
	 */
	@Override
	public void channelReadComplete(ChannelHandlerContext channelHandlerContext) throws Exception {
		channelHandlerContext.flush();
	}

	/**
	 * 接收消息
	 *
	 * @param channelHandlerContext
	 *            channelHandlerContext
	 * @param msg
	 *            msg
	 */
	@Override
	protected void messageReceived(ChannelHandlerContext channelHandlerContext, Object msg) throws Exception {
		Channel channel = channelHandlerContext.channel();
		if (!webSocketClientHandshaker.isHandshakeComplete()) {
			webSocketClientHandshaker.finishHandshake(channel, (FullHttpResponse) msg);
			handshakeFuture.setSuccess();
			// 将当前登陆用户保存起来
			WebSocketNettyUsers.put(getUserNameInPath(), channel);
			return;
		}
		channelHandlerContext.flush();

		if (msg instanceof FullHttpResponse) {
			FullHttpResponse response = (FullHttpResponse) msg;
			throw new IllegalStateException("Unexpected FullHttpResponse (getStatus=" + response.status() + ", content="
					+ response.content().toString(CharsetUtil.UTF_8) + ')');
		}
	}

	/**
	 * 获取登陆用户的方法
	 *
	 * @return 用户名
	 */
	private String getUserNameInPath() {
		String path = webSocketClientHandshaker.uri().getPath();
		int i = path.lastIndexOf("/");
		return path.substring(i + 1, path.length());
	}
}
